package com.hitqz.robot.driver.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.hitqz.robot.api.business.enums.FormConfigEnum;
import com.hitqz.robot.api.business.enums.RobotParamsFormFieldEnum;
import com.hitqz.robot.api.business.event.FormUpdateEvent;
import com.hitqz.robot.api.common.dto.form.FormFieldConfigUpdateDto;
import com.hitqz.robot.driver.communication.NetworkServiceThreadPool;
import com.hitqz.robot.driver.communication.SerialPortServer;
import com.hitqz.robot.driver.communication.TcpClient;
import com.hitqz.robot.driver.netty.handler.SensorHandler;
import com.hitqz.robot.driver.util.KcToolkit;
import com.hitqz.robot.driver.util.M518Toolkit;
import com.hitqz.robot.driver.util.TasLan464Toolkit;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@AllArgsConstructor
@Slf4j
public class KcParamsListener {

    @EventListener
    public void onParamsUpdate(FormUpdateEvent event) {
        NetworkServiceThreadPool.dealEvent(() -> {
            String formName = event.getFormName();
            if (!Objects.equals(formName, FormConfigEnum.ROBOT_PARAMS_CONFIG.getFormName())) {
                return;
            }
            List<FormFieldConfigUpdateDto> fields = event.getUpdateFields();
            try {
                this.updateRobotParams(fields);
            } catch (Exception e) {
                log.error("[kc]机器人参数配置更新异常", e);
            }
            log.info("[kc]机器人参数配置更新");
        });
    }


    private void updateRobotParams(List<FormFieldConfigUpdateDto> fields) throws InterruptedException {
        if (fields.isEmpty()) {
            return;
        }
        for (FormFieldConfigUpdateDto field : CollUtil.emptyIfNull(fields)) {
            try {
                String name = field.getFieldName();
                RobotParamsFormFieldEnum fieldEnum = RobotParamsFormFieldEnum.fromFieldName(name);
                if (fieldEnum == null) {
                    continue;
                }
                switch (fieldEnum) {
                    case CHARGE_POS_CODE:
                        KcToolkit.chargePosCode = field.getCurrentValue();
                        break;
                    case CHARGE_HOME_INSIDE_DOOR_POS_CODE:
                        KcToolkit.chargeHomeInsideDoorPosCode = field.getCurrentValue();
                        break;
                    case CHARGE_HOME_OUTSIDE_DOOR_POS_CODE:
                        KcToolkit.chargeHomeOutsideDoorPosCode = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_IP:
                        TasLan464Toolkit.tasLan464Ip = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM1_PORT:
                        TasLan464Toolkit.tasLan464Com1Port = Integer.parseInt(field.getCurrentValue());
                        break;
                    case TAS_LAN_464_COM2_PORT:
                        TasLan464Toolkit.tasLan464Com2Port = Integer.parseInt(field.getCurrentValue());
                        break;
                    case TAS_LAN_464_COM3_PORT:
                        TasLan464Toolkit.tasLan464Com3Port = Integer.parseInt(field.getCurrentValue());
                        break;
                    case TAS_LAN_464_COM4_PORT:
                        TasLan464Toolkit.tasLan464Com4Port = Integer.parseInt(field.getCurrentValue());
                        break;
                    case TAS_LAN_464_COM1_NAME:
                        TasLan464Toolkit.tasLan464Com1Name = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM2_NAME:
                        TasLan464Toolkit.tasLan464Com2Name = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM3_NAME:
                        TasLan464Toolkit.tasLan464Com3Name = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM4_NAME:
                        TasLan464Toolkit.tasLan464Com4Name = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM1_MESSAGE_TEXT:
                        TasLan464Toolkit.tasLan464Com1MessageText = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM2_MESSAGE_TEXT:
                        TasLan464Toolkit.tasLan464Com2MessageText = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM3_MESSAGE_TEXT:
                        TasLan464Toolkit.tasLan464Com3MessageText = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM4_MESSAGE_TEXT:
                        TasLan464Toolkit.tasLan464Com4MessageText = field.getCurrentValue();
                        break;
                    case TAS_LAN_464_COM1_BRAND:
                        TasLan464Toolkit.tasLan464Com1Brand = field.getCurrentValue();
                    case TAS_LAN_464_COM2_BRAND:
                        TasLan464Toolkit.tasLan464Com2Brand = field.getCurrentValue();
                    case TAS_LAN_464_COM3_BRAND:
                        TasLan464Toolkit.tasLan464Com3Brand = field.getCurrentValue();
                    case TAS_LAN_464_COM4_BRAND:
                        TasLan464Toolkit.tasLan464Com4Brand = field.getCurrentValue();
                    case M518R_COM_NAME:
                        M518Toolkit.m518ComName = field.getCurrentValue();
                        break;
                    case M518R_COM_OPEN_MESSAGE_TEXT:
                        M518Toolkit.m518OpenDoorText = field.getCurrentValue();
                        break;
                    case M518R_COM_CLOSE_MESSAGE_TEXT:
                        M518Toolkit.m518CloseDoorText = field.getCurrentValue();
                        break;
                    default:
                        break;
                }
            } catch (Exception e) {
                log.error("[track]机器人参数更新异常", e);
            }
        }
        // 创建监听客户端
        if (TasLan464Toolkit.com1TcpClient == null
                || !Objects.equals(TasLan464Toolkit.com1TcpClient.getPort(), TasLan464Toolkit.tasLan464Com1Port)
                || !Objects.equals(TasLan464Toolkit.com1TcpClient.getHost(), TasLan464Toolkit.tasLan464Ip)) {
            if (TasLan464Toolkit.com1TcpClient != null) {
                TasLan464Toolkit.com1TcpClient.shutdown();
                TasLan464Toolkit.com1TcpClient = null;
            }
            NetworkServiceThreadPool.creatNetworkServerOrClient(() -> {
                try {
                    if (StrUtil.isBlank(TasLan464Toolkit.tasLan464Ip) || TasLan464Toolkit.tasLan464Com1Port == null || StrUtil.isBlank(TasLan464Toolkit.tasLan464Com1MessageText)) {
                        return;
                    }
                    TcpClient com1TcpClient = new TcpClient("taslan464-com1-client", TasLan464Toolkit.tasLan464Ip, TasLan464Toolkit.tasLan464Com1Port, new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(TasLan464Toolkit.tasLan464Com1Name, new SensorHandler(TasLan464Toolkit.tasLan464Com1Brand));
                        }
                    });
                    TasLan464Toolkit.com1TcpClient = com1TcpClient;
                    com1TcpClient.connectAsync();
                } catch (Exception e) {
                    log.info("[kc]tas-lan-464 com1 client error", e);
                }
            });
        }
        // 创建监听客户端
        if (TasLan464Toolkit.com2TcpClient == null
                || !Objects.equals(TasLan464Toolkit.com2TcpClient.getPort(), TasLan464Toolkit.tasLan464Com2Port)
                || !Objects.equals(TasLan464Toolkit.com2TcpClient.getHost(), TasLan464Toolkit.tasLan464Ip)) {
            if (TasLan464Toolkit.com2TcpClient != null) {
                TasLan464Toolkit.com2TcpClient.shutdown();
                TasLan464Toolkit.com2TcpClient = null;
            }
            NetworkServiceThreadPool.creatNetworkServerOrClient(() -> {
                try {
                    if (StrUtil.isBlank(TasLan464Toolkit.tasLan464Ip) || TasLan464Toolkit.tasLan464Com2Port == null || StrUtil.isBlank(TasLan464Toolkit.tasLan464Com2MessageText)) {
                        return;
                    }
                    TcpClient com2TcpClient = new TcpClient("taslan464-com2-client", TasLan464Toolkit.tasLan464Ip, TasLan464Toolkit.tasLan464Com2Port, new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(TasLan464Toolkit.tasLan464Com2Name, new SensorHandler(TasLan464Toolkit.tasLan464Com2Brand));
                        }
                    });
                    TasLan464Toolkit.com2TcpClient = com2TcpClient;
                    com2TcpClient.connectAsync();
                } catch (Exception e) {
                    log.info("[kc]tas-lan-464 com2 client error", e);
                }
            });
        }
        if (TasLan464Toolkit.com3TcpClient == null
                || !Objects.equals(TasLan464Toolkit.com3TcpClient.getPort(), TasLan464Toolkit.tasLan464Com3Port)
                || !Objects.equals(TasLan464Toolkit.com3TcpClient.getHost(), TasLan464Toolkit.tasLan464Ip)) {
            if (TasLan464Toolkit.com3TcpClient != null) {
                TasLan464Toolkit.com3TcpClient.shutdown();
                TasLan464Toolkit.com3TcpClient = null;
            }
            NetworkServiceThreadPool.creatNetworkServerOrClient(() -> {
                try {
                    if (StrUtil.isBlank(TasLan464Toolkit.tasLan464Ip) || TasLan464Toolkit.tasLan464Com3Port == null|| StrUtil.isBlank(TasLan464Toolkit.tasLan464Com3MessageText)) {
                        return;
                    }
                    TcpClient com3TcpClient = new TcpClient("taslan464-com3-client", TasLan464Toolkit.tasLan464Ip, TasLan464Toolkit.tasLan464Com3Port, new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(TasLan464Toolkit.tasLan464Com3Name, new SensorHandler(TasLan464Toolkit.tasLan464Com3Brand));
                        }
                    });
                    TasLan464Toolkit.com3TcpClient = com3TcpClient;
                    com3TcpClient.connectAsync();
                } catch (Exception e) {
                    log.info("[kc]tas-lan-464 com3 client error", e);
                }
            });
        }
        if (TasLan464Toolkit.com4TcpClient == null
                || !Objects.equals(TasLan464Toolkit.com4TcpClient.getPort(), TasLan464Toolkit.tasLan464Com4Port)
                || !Objects.equals(TasLan464Toolkit.com4TcpClient.getHost(), TasLan464Toolkit.tasLan464Ip)) {
            if (TasLan464Toolkit.com4TcpClient != null) {
                TasLan464Toolkit.com4TcpClient.shutdown();
                TasLan464Toolkit.com4TcpClient = null;
            }
            NetworkServiceThreadPool.creatNetworkServerOrClient(() -> {
                try {
                    if (StrUtil.isBlank(TasLan464Toolkit.tasLan464Ip) || TasLan464Toolkit.tasLan464Com4Port == null || StrUtil.isBlank(TasLan464Toolkit.tasLan464Com4MessageText)) {
                        return;
                    }
                    TcpClient com4TcpClient = new TcpClient("taslan464-com4-client", TasLan464Toolkit.tasLan464Ip, TasLan464Toolkit.tasLan464Com4Port, new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(TasLan464Toolkit.tasLan464Com4Name, new SensorHandler(TasLan464Toolkit.tasLan464Com4Brand));
                        }
                    });
                    TasLan464Toolkit.com4TcpClient = com4TcpClient;
                    com4TcpClient.connectAsync();
                } catch (Exception e) {
                    log.info("[kc]tas-lan-464 com4 client error", e);
                }
            });
        }
        if (M518Toolkit.m518SerialPortServer == null || !Objects.equals(M518Toolkit.m518SerialPortServer.getComName(), M518Toolkit.m518ComName)) {
            if (M518Toolkit.m518SerialPortServer != null) {
                M518Toolkit.m518SerialPortServer.close();
            }
            NetworkServiceThreadPool.creatNetworkServerOrClient(() -> {
                SerialPortServer serialPortServer = new SerialPortServer();
                M518Toolkit.m518SerialPortServer = serialPortServer;
                serialPortServer.bind("M518R", M518Toolkit.m518ComName, 9600, 8, 1, 0, new byte[]{(byte) 0x57, (byte) 0x4A});
            });
        }
        // 需要设置到控制器的,先验证通讯
        int waitTimes = 60;
        for (int i = 0; i < waitTimes; i++) {
            if (KcToolkit.client.readyToSend()) {
                break;
            } else if (i == waitTimes - 1) {
                log.warn("[kc] update controller params failed, client is not ready.");
                return;
            }
            TimeUnit.SECONDS.sleep(2);
        }
        // 发送设置参数指令

    }

}
    
